/**
 * Created by jiachenpan on 16/11/18.
 */

import moment from "moment"




// 定义一些常量
const x_PI = 3.14159265358979324 * 3000.0 / 180.0
const PI = 3.1415926535897932384626
const a = 6378245.0
const ee = 0.00669342162296594323

const  crc16_ccitt_table = [
    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
    0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
    0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
    0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
    0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
    0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
    0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
    0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
    0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
    0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
    0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
    0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
    0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
    0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
    0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
    0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
    0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
]

var frameNo = 0;

export const utils = {

    TCP_BODY_HEAD : "245F" ,
    TCP_BODY_TAIL : "237E" ,
    TCP_VALUE_SPLIT : "2C" ,
    TCP_LIST_ITEM_SPLIT : "7C" ,
    AMAP_KEY : "f2e8b33e7cadf833c0ba73c0130ef364" ,
    AMAP_SK : "70bc9e1d6c7acc246c4ddea1d5c8763f" ,

    isEmpty: (str) => {
        if(utils.trim(str) === '' || str === undefined || str == null){
            return true;
        }
        return false;
    },

    isNotEmpty: (str) => {
        return !utils.isEmpty(str);
    },

    isObjEmpty: (str) => {
        if(str === undefined || str == null){
            return true;
        }
        return false;
    },

    isObjNotEmpty: (str) => {
        return !utils.isObjEmpty(str);
    },

    trim : (s) => {
        return s.replace(/(^\s*)|(\s*$)/g, "");
    },

    ltrim : (s) => {
        return s.replace(/(^\s*)/g, "");
    },
    rtrim : (s) => {
        return s.replace(/(\s*$)/g, "");
    },

    // 对象深度拷贝
    deepClone: (source) =>  {
        // 判断复制的目标是数组还是对象
        const targetObj = source.constructor === Array ? [] : {}
        for (const keys in source) {
            if (source.hasOwnProperty(keys)) {
                if (source[keys] && typeof source[keys] === 'object') {
                    // 如果值是对象，就递归一下
                    targetObj[keys] = source[keys].constructor === Array ? [] : {}
                    targetObj[keys] = utils.deepClone(source[keys])
                } else {
                    // 如果不是，就直接赋值

                    if(utils.isObjNotEmpty(source[keys])){
                        targetObj[keys] = source[keys]
                    }
                }
            }
        }
        return targetObj
    },


    //十六进制字符串转字节数组
    str2Bytes : (str) => {
        var pos = 0;
        var len = str.length;
        if(len %2 != 0)
        {
            return null;
        }
        len /= 2;
        var hexA = new Array();
        for(var i=0; i<len; i++)
        {
            var s = str.substr(pos, 2);
            var v = parseInt(s, 16);
            hexA.push(v);
            pos += 2;
        }
        return hexA;
    },
    decToHex(num){
        return num.toString(16).toUpperCase();
    },
    //字符串转16进制ASCII
    str2HexAscii : (str, prefix='' ,split='') => {
        str = "" + str;
        if(str.length < 1){
            return false;
        }
        var arr = str.split("");
        var txt = '';
        arr.forEach(function(v,i){
            txt += prefix + utils.decToHex(v.charCodeAt()) + split;
        });
        return txt;
    },

//字节数组转十六进制字符串
    bytes2Str :  (arr) =>  {
        var str = "";
        for(var i=0; i<arr.length; i++)
        {
            var tmp = arr[i].toString(16);
            if(tmp.length == 1)
            {
                tmp = "0" + tmp;
            }
            str += tmp;
        }
        return str;
    },

    getCurrentMoment : (timeZone = 8) => {
        return moment().utcOffset(timeZone);
    },

    getCurrentMomentAdd : (moment = moment() ,format = 'YYYY-MM-DD HH:mm:ss' , count=0 , unit='days') => {
        return moment.add(count , unit).format(format);
    },

    getCurrentTime : (format = 'YYYY-MM-DD HH:mm:ss' , timeZone = 8) => {
        return moment().utcOffset(timeZone).format(format);
    },

    getCurrentTimeAdd : (format = 'YYYY-MM-DD HH:mm:ss' , timeZone = 8 , count=0 , unit='days') => {
        return moment().utcOffset(timeZone).add(count , unit).format(format);
    },



    strToTs:(str , format = 'YYYY-MM-DD HH:mm:ss' , timeZone = 8) => {
        return moment(str,format).utcOffset(timeZone).unix();
    },

    crc16 : (data) => {
        var start = 0;
        var len = data.length;
        var crc_reg = 0x0000;
        while (len-- > 0) {
            crc_reg = (crc_reg >> 8) ^ crc16_ccitt_table[(crc_reg ^ data[start++]) &0xff];
        }
        crc_reg ^= 0x0000;
        return  crc_reg.toString(16).toLocaleUpperCase();
    },


/**
 *
 * @param sn
 * @param deviceState @code
 * {
 *                charge: false,
 *               lowPower : false ,
 *             static : false,
 *            battery : 55,
 *         }
 * @param cmd
 * @param body
 */
    generateTcpData : (sn , deviceState, cmd ,  body ) => {
        frameNo++;
        const length = body.length/2;
        const battery = deviceState['battery'];

        const still = deviceState['static'] ? 1 : 0;
        const lowPower = deviceState['lowPower'] ? 1 : 0;
        const charge = deviceState['charge'] ? 1 : 0;

        const statusFlagStr = ("" + still + charge + lowPower).padStart(8 , "0");
        const statusFlag = parseInt(statusFlagStr , 2);

        const sendDataHeadAndPayload = (
            utils.TCP_BODY_HEAD
            + length.toString(16).padStart(4,"0")
            + frameNo.toString(16).padStart(4,"0")
            + sn
            + battery.toString(16).padStart(2,"0")
            + statusFlag.toString(16).padStart(2,"0")
            + Number(cmd).toString(16).padStart(4,"0")
            + body).toLocaleUpperCase();
        const crcResult = utils.crc16(utils.str2Bytes(sendDataHeadAndPayload)).padStart(4,"0");
        const sendData = sendDataHeadAndPayload + crcResult + utils.TCP_BODY_TAIL;

        return sendData;
    },

    gpsToDegMin: (gpsData , i) => {
        gpsData = Number(gpsData);
        const degress = Math.floor(gpsData) * 100;
        const min = (gpsData - Math.floor(gpsData)) * 60
        const num = degress + min;
        const numDouble = num - 0.01*i;
        return numDouble.toFixed(5);

    },


    CACHE_KEY :{
        TCP_CONFIG : "TCP_CONFIG"
    },

    setCacheObject : (key , value) => {
        localStorage.setItem(key, JSON.stringify(value));
    },
    getCacheObject : (key) => {
        return JSON.parse(localStorage.getItem(key));
    },

    setCacheString : (key , value) => {
        localStorage.setItem(key, value);
    },
    getCacheString : (key) => {
        return localStorage.getItem(key);
    },

    delCache :(key) => {
        return localStorage.removeItem(key);
    },



    /**
     * 经度转换
     * @param { Number } lng
     * @param { Number } lat
     */
    transformlat :function(lng, lat) {
        var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng))
        ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0
        ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0
        ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0
        return ret
    },

    /**
    * 纬度转换
    * @param { Number } lng
    * @param { Number } lat
    */
    transformlng:function  (lng, lat) {
        var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng))
        ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0
        ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0
        ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0
        return ret
    },

/**
     * 判断是否在国内，不在国内则不做偏移
     * @param {*} lng
     * @param {*} lat
     */
    outOfChina:function (lng, lat) {
        return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false)
    },
    /**
     * WGS84坐标系转火星坐标系GCj02 / 即WGS84 转谷歌、高德
     * @param { Number } lng
     * @param { Number } lat
     */
    wgs84togcj02 :function(lng, lat) {
        if (utils.outOfChina(lng, lat)) {
            return [lng, lat]
        }
        else {
            var dlat = utils.transformlat(lng - 105.0, lat - 35.0)
            var dlng = utils.transformlng(lng - 105.0, lat - 35.0)
            var radlat = lat / 180.0 * PI
            var magic = Math.sin(radlat)
            magic = 1 - ee * magic * magic
            var sqrtmagic = Math.sqrt(magic)
            dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI)
            dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI)
            const mglat = lat + dlat
            const mglng = lng + dlng
            return [mglng, mglat]
        }
    },

    /**
     * GCJ02（火星坐标系） 转换为 WGS84 / 即谷歌高德转WGS84
     * @param { Number } lng
     * @param { Number } lat
     */
    gcj02towgs84 :function(lng, lat) {
        if (utils.outOfChina(lng, lat)) {
            return [lng, lat]
        }
        else {
            var dlat = utils.transformlat(lng - 105.0, lat - 35.0)
            var dlng = utils.transformlng(lng - 105.0, lat - 35.0)
            var radlat = lat / 180.0 * PI
            var magic = Math.sin(radlat)
            magic = 1 - ee * magic * magic
            var sqrtmagic = Math.sqrt(magic)
            dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI)
            dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI)
            const mglat = lat + dlat
            const mglng = lng + dlng
            return [lng * 2 - mglng, lat * 2 - mglat]
        }
    },


    CMD : {
        GET_OTA_PACKAGE : 23,
        GET_OTA_CONFIG : 24,
        TEMP_BRAKE_BLOCK : 25,
        AUTO_POSITION : 26,
        GPS_BRIEF : 27,
        FAULT_REPORT : 28,
        LOAD : 29,
        VERSION : 30,
        AUTO_INFLATE : 31,
        TPMS_V3 : 32,
        EVENT_V3 : 33,
        HEART_V3 : 36,
        REG_V3 : 37,
        DEVICE_LOGIN_V3 : 38,
        HUB_TEMP : 39,
        AUTO_BIND_V3 : 42,
        GET_CARRIER_TYRE_CONFIG :43 ,
        GET_DEVICE_CONFIG : 44,
        AUTO_POSITION_NO : 45,
        AUTO_UNBIND_V3 : 46,
        PT_CARRIER_NO : 47,
        PT_LOCATION_SENSOR : 48,
        AUTO_INFLATE_ERROR : 49,
        SENSOR_AROUND : 51,
        SENSOR_AROUND_ADVANCE : 52,
        TPMS_LOAD : 53,
        AUTO_POSITION_FLAG : 54,
        AUTO_POSITION_REPLENISH : 55,
        TPMS_ACC : 56,
        TPMS_ESTIMATE : 57,
        SYNC_COLD_PRESSURE : 59,
        GET_OTA_PACKAGE_BIG : 60,
        GET_OTA_CONFIG_BIG : 61,
        VERSION_PERIPHERAL : 63,
        GET_OTA_PACKAGE_PERIPHERAL : 64,
        GET_OTA_CONFIG_PERIPHERAL : 65,
        SYNC_PERIPHERAL : 66,
        AUTO_POSITION_NO_TPMS : 67,
        AUTO_POSITION_FLAG_TPMS : 68,
        TEST_V3 : 65531,
        DEVICE_INFO : 65532,
        DEBUG_INFO : 65533,
        GET_UTC_TIME : 65534,
        ACK : 65535,
    }

}
